﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Motoball.screenmanager;
using Motoball;
using Motoball.screens;
using Microsoft.Xna.Framework.Input;

namespace Motoball.Paddles
{
    public class Paddle
    {
        #region Values
        //energy-management
        public int energy = 5;
        public int maxEnergy = 7;
        public float energyTimer = 0f;

        public bool active = true;
        public int selectedPaddle = -1;
        Paddle otherPaddle;

        int playerIndex;
        public float speed = 0.99f;
        
        Vector3 col3;
        Color color;
        public float friction = 0.83f;
        //movement delta
        public float delta = 0.0f;
        public float rotation = 0.0f;
        protected float startRotation = 0.0f;
        
        public BasicModel basicModel;
        public PaddleContent paddleContent;
        protected float innerRadius;
        #endregion
        public float scale = 1.0f;
        GameplayScreen screen;

       
        public static InputState input;
        public Paddle(Color color, GameplayScreen screen, int playerIndex)
        {
            this.playerIndex = playerIndex;
            Screen = screen;
            
            Color = color;
        }

        #region Properties
        public Paddle OtherPaddle
        {
            get { return otherPaddle; }
            set { otherPaddle = value; }
        }
        public float InnerRadius
        {
            get { return innerRadius; }
        }
       
        public GameplayScreen Screen
        {
            get { return screen; }
            set { screen = value; }
        }
        public float Speed
        {
            get { return speed; }
            set { speed = value; }
        }
        public float Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }
        public float Friction
        {
            get { return friction; }
        }
        public float MaxPaddleDistance
        {
            get { return paddleContent.maxPaddleDistance; }
        }
        public float PaddleWidth
        {
            get { return paddleContent.paddleWidth; }
        }
        public float PaddleHeight
        {
            get { return paddleContent.paddleHeight; }
        }
        public float Delta
        {
            get { return delta; }
            set { delta = value; }
        }
        public float StartRotation
        {
            get { return startRotation; }
            set { startRotation = value; }
        }
        public Matrix World
        {
            get { return basicModel.World; }
        }
        public int PlayerIndex
        {
            get { return playerIndex; }
        }
        public Color Color
        {
            get { return color; }
            set
            {
                color = value;
                col3 = new Vector3(color.R / 255f, color.G / 255f, color.B / 255f);
            }
        }
        public Vector3 Col3
        {
            get { return col3; }
            set { col3 = value; }
        }
        public Camera Camera
        {
            get { return GameScreen.Camera; }
        }
        public float BallHeight
        {
            get { return paddleContent.ballHeight; }
        }
        #endregion

        #region Methods
        public void NextEnergyLevel()
        {
            if (++energy > maxEnergy)
                energy = maxEnergy;
            else
            {
                AudioManager.PlayCue("energy_load");
                RefreshEnergyDisplay();
            }
            //memo: TODO:add graphical representation
        }
        public void RefreshEnergyDisplay()
        {
            Screen.ChangeEnergy(playerIndex, energy);
            
        }
        public void Initialize(int type)
        {
            switch (type)
            {
                    //Beamer
                case 0:
                    paddleContent = new Beamer(this);
                    break;
                //Crusher
                case 1:
                    paddleContent = new Crusher(this);
                    break;
                //Racer
                case 2:
                    paddleContent = new Racer(this);
                    break;
                ////Roland
                //case 3:
                //    paddleContent = new Roland(this);
                //    break;
                default:
                    
                    break;
            }
            innerRadius = ContentStorage.CurrentRingSize - paddleContent.paddleHeight/2;
            paddleContent.Initialize(innerRadius);

           // Screen.ChargeUp(playerIndex, energy + 1);
            Reset();
        }
        /// <summary>
        /// for debug-purpose only
        /// </summary>
        public void Recalc()
        {
            innerRadius = ContentStorage.CurrentRingSize - paddleContent.paddleHeight / 2;

            //GameplayScreen gameplay = (GameplayScreen)GameScreen.screenManager.GetScreen("gameplayScreen");
            //gameplay.paddleDistance = gameplay.player1.PaddleWidth + gameplay.player2.PaddleWidth;

            ////memo: TODO: load background depending on ringsize
            ////currentringsize + half-ball-size
            //float paddleSizeMax = gameplay.player1.PaddleHeight;
            //if (gameplay.player2.PaddleHeight > paddleSizeMax)
            //    paddleSizeMax = gameplay.player2.PaddleHeight;
            //gameplay.innerRadius = ContentStorage.CurrentRingSize - paddleSizeMax / 2 - 350;
            //gameplay.outerGameRadius = gameplay.innerRadius + 200;
        }
        public float Distance(Paddle otherPaddle)
        {
            return Vector3.Distance(World.Translation, otherPaddle.World.Translation);
        }
        public void LoadContent(ContentManager content, int type)
        {
            if (selectedPaddle != type)
            {
                selectedPaddle = type;
                switch (selectedPaddle)
                {
                        //Beamer
                    case 0:
                        basicModel = new BasicModel(content.Load<Model>("Models\\Beamer"));
                        scale = 1f;
                        break;
                    //Crusher
                    case 1:
                        basicModel = new BasicModel(content.Load<Model>("Models\\Crusher"));
                        scale = 1f;
                        break;
                    //Racer
                    case 2:
                        basicModel = new BasicModel(content.Load<Model>("Models\\Racer"));
                        scale = 0.8f;
                        break;
                    ////Roland
                    //case 3:
                    //    basicModel = new BasicModel(content.Load<Model>("Models\\Roland"));
                    //    scale = 1f;
                    //    break;
                    default:
                        break;
                }
                
                Initialize(type);
            }
        }
        /// <summary>
        /// resets paddle' position and movement memory
        /// </summary>
        public virtual void Reset()
        {
            speed = paddleContent.initialSpeed;
            delta = 0;
            rotation = startRotation;

            basicModel.World = Matrix.CreateScale(scale);
            basicModel.World *= Matrix.CreateRotationX(-MathHelper.PiOver2);
            basicModel.World *= Matrix.CreateTranslation(0.0f, 0.0f, InnerRadius);
            basicModel.World *= Matrix.CreateRotationY(Rotation);
            
           paddleContent.Reset();
        }
        public void Draw(GameTime gameTime)
        {
            GameScreen.screenManager.AddDebugString("player "+playerIndex.ToString()+":"+paddleContent.paddleHeight.ToString());
            basicModel.model.Root.Transform = World;
            if(GameScreen.screenManager.currentDrawSetId == "default")
                paddleContent.UpdateAnimation(gameTime);
            foreach (ModelMesh mesh in basicModel.model.Meshes)
            {

                foreach (BasicEffect be in mesh.Effects)
                {
                    be.DiffuseColor = basicModel.diffColors[mesh.Name];
                    be.SpecularColor = col3/10f;
                   // be.EmissiveColor = color/20f;
                    
                }

            }
            basicModel.Draw(Camera);
        }
        protected void UpdateEnergy(GameTime gameTime)
        {
            if (energy < maxEnergy)
            {
                energyTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (energyTimer >= 2f)
                {
                    NextEnergyLevel();
                    energyTimer -= 2f;
                    //GameScreen.screenManager.GetDrawSet("chargeBloom" +
                    //    playerIndex.ToString()).SetBloomValues(1f);
                    //Screen.ChargeUp(playerIndex, energy + 1);
                }
                //else
                //{
                //    //set bloom-values for charging
                //    float test = MathHelper.Lerp(1f, GameScreen.screenManager.bloomVar, energyTimer / 2f);
                //    GameScreen.screenManager.GetDrawSet("chargeBloom" + playerIndex.ToString()).
                //        SetBloomValues
                //        (MathHelper.Lerp(1f, GameScreen.screenManager.bloomVar, energyTimer / 2f));
                //}
            }
        }
       
        public virtual void Update(GameTime gameTime)
        {
            
            //Recalc();
            UpdateEnergy(gameTime);
            if (!paddleContent.movementDisabled)
            {
//#if !XBOX
//                if (playerIndex == 0)
//                {
//                    if (GameScreen.screenManager.Input.LeftP1)
//                        Delta -= Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
//                    if (GameScreen.screenManager.Input.RightP1)
//                        Delta += Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
                    
//                }

//                else
//                {
//                    if (GameScreen.screenManager.Input.LeftP2)
//                        Delta -= Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
//                    if (GameScreen.screenManager.Input.RightP2)
//                        Delta += Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
//                }
//#else
                float tempX = GameScreen.screenManager.Input.LeftStick(playerIndex).X;
                if (playerIndex == 1)
                    tempX = -tempX;
                Delta += Speed * (float)gameTime.ElapsedGameTime.TotalSeconds * tempX;
                   
                
//#endif
            }
            Delta *= Friction;
            Rotation += Delta;
            if (Rotation >= MathHelper.TwoPi)
                Rotation -= MathHelper.TwoPi;
            else if (Rotation < 0.0f)
                Rotation += MathHelper.TwoPi;

            basicModel.World = Matrix.CreateScale(scale);
            basicModel.World *= Matrix.CreateRotationX(-MathHelper.PiOver2);
            basicModel.World *= Matrix.CreateTranslation(0.0f, 0.0f, InnerRadius);
            basicModel.World *= Matrix.CreateRotationY(Rotation);

            paddleContent.Update(gameTime);
            
        }
        public Vector3 RotateY(Vector3 vector, float radians)
        {
            Vector3 temp = vector;
            temp.X = vector.X * (float)Math.Cos(radians) - vector.Z * (float)Math.Sin(radians);
            temp.Z = vector.X * (float)Math.Sin(radians) + vector.Z * (float)Math.Cos(radians);
            return temp;
        }
        
        #endregion
    }
}
